
/*******************************************************************************
   @file    devio.h
   @author  H.M.Shim (elecage@gmail.com)
   @version
   @date    2013. 7. 25.
   @brief   디바이스 드라이버 관리자 헤더파일.
   모든 디바이스 드라이버는 devInit, devOpen, devRead, devWrite,
 devIoctl, devClose 함수를 이용하여 제어한다. 각 디바이스 드라이버는 이 함수들에 매칭되는 각각의 함수를 작성해서
   등록한다. 만일 명령줄 입력을 사용할 경우 추가되는 함수를 사용한다. 명령줄 입력을 사용하기 위해서는 USE_CMDLINE이 정의되어야 한다.
  ******************************************************************************
  The MIT License (MIT)

Copyright (c) 2013 <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
  ******************************************************************************
  */


/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DEVIO_H_
#define DEVIO_H_
/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include "unistd.h"
/**
 * @defgroup devio Device I/O Group
 * @ingroup devioTypedef devioStruct devioEnum devioDefine devioFuncs
 */
/**
 * @defgroup devioTypedef Device I/O typedef
 * @{
 */
/* Exported typdef -----------------------------------------------------------*/
typedef int32_t (*OpenFunc)(const int8_t *devname, int32_t flags);
typedef ssize_t (*WriteFunc)(int32_t dd, const void *buf, size_t n);
typedef ssize_t	(*ReadFunc)(int32_t dd, void *buf, size_t nbytes);
typedef ssize_t (*IoctlFunc)(int32_t dd, int32_t request, void* data);
typedef int32_t (*CloseFunc)(int32_t dd);
typedef int32_t (*CmdFunc)(int32_t argc, int8_t *argv[]);

typedef void (*InterruptHandleFunc)(void);
/**
 * @}
 * @defgroup devioStruct Device I/O Structures
 * @{
 */

/**
 * @struct DeviceStructure
 * @brief 디바이스 드라이버 제어 함수들의 구조체.
 * 모든 디바이스 드라이버는 다음에 해당하는 함수들을 만들어야 한다.
 */
typedef struct {
	int8_t*		devname;		/**< @brief 장치명. 문자열로 표현한다. 예)"gpioa" */
	int32_t		dd;				/**< @brief 장치 디스크립터. */
	OpenFunc	openFunc;		/**< @brief 장치 사용 시작 함수 */
	WriteFunc	writeFunc;		/**< @brief 장치 쓰기 함수. 장치로 데이터를 출력할 때 사용한다.*/
	ReadFunc	readFunc;		/**< @brief 장치 읽기 함수. 장치로부터 데이터를 입력받을 때 사용한다. */
	IoctlFunc	ioctlFunc;		/**< @brief 장치 설정 함수 */
	CloseFunc	closeFunc;		/**< @brief 장치 사용 종료 함수 */
#ifdef USE_CMDLINE
	CmdFunc		openCmdFunc;	/**< @brief 장치 사용 시작 명령줄 함수. USE_CMDLINE이 정의될 때만 사용가능하다. */
	CmdFunc		readCmdFunc;	/**< @brief 장치 읽기 명령줄 함수. USE_CMDLINE이 정의될 때만 사용가능하다. */
	CmdFunc		writeCmdFunc;	/**< @brief 장치 쓰기 명령줄 함수. USE_CMDLINE이 정의될 때만 사용가능하다. */
	CmdFunc		ioctlCmdFunc;	/**< @brief 장치 설정 명령줄 함수. USE_CMDLINE이 정의될 때만 사용가능하다. */
	CmdFunc		closeCmdFunc;	/**< @brief 장치 사용 중지 명령줄 함수. USE_CMDLINE이 정의될 때만 사용가능하다. */
#endif /* USE_CMDLINE */
}DeviceStructure;

/**
 * @}
 * @defgroup devioEnum Device I/O Enumerations
 * @{
 */
/* Exported constants --------------------------------------------------------*/
/** @brief 장치 디스크립터 */
enum DeviceDescriptor {
	Dev_NULL = 0,				/**< 아무 장치도 아님 */
	Dev_GPIOA,					/**< GPIO A 포트 */
	Dev_GPIOB,					/**< GPIO B 포트 */
	Dev_GPIOC,					/**< GPIO C 포트 */
	Dev_GPIOD,					/**< GPIO D 포트 */
	Dev_GPIOE,					/**< GPIO E 포트 */
	Dev_GPIOF,					/**< GPIO F 포트 */
	Dev_GPIOG,					/**< GPIO G 포트 */
	Dev_GPIOH,					/**< GPIO H 포트 */
	Dev_GPIOI,					/**< GPIO I 포트 */
	Dev_Timer1,					/**< 타이머 1번 */
	Dev_Timer2,					/**< 타이머 2번 */
	Dev_Timer3,					/**< 타이머 3번 */
	Dev_SPI1,					/**< SPI 1번 */
	Dev_SPI2,					/**< SPI 2번 */
	Dev_SPI3,					/**< SPI 3번 */
	Dev_SPI4,					/**< SPI 4번 */
	Dev_SPI5,					/**< SPI 5번 */
	DEV_SPI6,					/**< SPI 6번 */
	Dev_I2C1,					/**< I2C 1번 */
	Dev_I2C2,					/**< I2C 2번  */
	Dev_I2C3,
	Dev_EAB1,
	DEV_EAB2,
	DEV_EAB3,
	Dev_Bone					/**< 테스트 장치 드라이버 */
};
/**
 * @}
 * @defgroup devioDefine	Device I/O Definitions
 * @{
 */

#define MAX_DEV_NUMBER	128					/**< @brief 장치를 등록할 수 있는 최대 개수 */
#define DEV_STAT_OPEN	1					/**< @brief 장치가 열려 있는 상태 */


#define DEV_ERR_UNREGISTERED_DEVICE	(-1)	/**< @brief 장치 오류 : 등록되지 않은 장치 */
#define DEV_ERR_ALREADY_OPEN		(-3)	/**< @brief 장치오류 : 이미 열려 있음 */
#define DEV_ERR_READ_ONLY			(-4)	/**< @brief 장치 오류 : 읽기 전용 장치에 쓰기를 시도할 때 발생 */
#define DEV_ERR_NOT_OPEN			(-6)	/**< @brief 장치 오류 : 열려있지 않음 */
#define DEV_ERR_INVALID_WRITE		(-7)	/**< @brief 장치 오류 : 잘못된 쓰기 */
#define DEV_ERR_INVALID_ARG			(-8)	/**< @brief 장치 오류 : 잘못된 인자 */

/* Open Flags */

#define DEV_RDONLY					0x10000000	/**< @brief 읽기 전용 장치 플래그. devOpen 함수에서 사용한다. */
#define DEV_WRONLY					0x20000000	/**< @brief 쓰기 전용 장치 플래그. devOpen 함수에서 사용한다. */
#define DEV_RDWR					0x30000000	/**< @brief 읽기 쓰기 모두 가능한 장치 플래그. devOpen 함수에서 사용한다. */


#define DEV_CMD_OPEN				((int8_t*)"open")	/**< @brief 명령줄 명령어. 열기 */
#define DEV_CMD_READ1				((int8_t*)"read")	/** @brief 명령줄 명령어. 읽기. full name */
#define DEV_CMD_READ2				((int8_t*)"r")		/**< @brief 명령줄 명령어. 읽기. 단축형 */
#define DEV_CMD_WRITE1				((int8_t*)"write")	/**< @brief 명령줄 명령어. 쓰기. full name */
#define DEV_CMD_WRITE2				((int8_t*)"w")		/**< @brief 명령줄 명령어. 쓰기. 단축형 */
#define DEV_CMD_IOCTL				((int8_t*)"ioctl")	/**< @brief 명령줄 명령어. 설정 */
#define DEV_CMD_CLOSE1				((int8_t*)"close")	/**< @brief 명령줄 명령어. 닫기. full name */
#define DEV_CMD_CLOSE2				((int8_t*)"c")		/**< @brief 명령줄 명령어. 닫기. 단축형 */

#define DEV_HELP_OPEN	((int8_t*)"Open device. ex) open gpio a")
#define DEV_HELP_READ	((int8_t*)"Read data from the device. ex) read gpio a")
#define DEV_HELP_WRITE	((int8_t*)"Write data to the device. ex) write gpio a PIN0 on PIN1 off")
#define DEV_HELP_CLOSE	((int8_t*)"Close device. ex) close gpioa")
#define DEV_HELP_IOCTL	((int8_t*)"I/O Control device. ex)ioctl gpioa")
/**
 * @}
 */
/* Exported macro ------------------------------------------------------------*/

/* Exported variables ------------------------------------------------------- */
extern DeviceStructure deviceTable[];
/* Exported functions ------------------------------------------------------- */
int32_t deviceIoInit();
int32_t devOpen(const int8_t *devname, int32_t flags);
ssize_t devWrite(int32_t dd, const void *buf, size_t n);
ssize_t devRead(int32_t dd, void *buf, size_t nbytes);
ssize_t devIoctl(int32_t dd, int32_t request, void* data);
int32_t devClose(int dd);
int32_t registerDevice(DeviceStructure device);

#ifdef USE_CMDLINE
int32_t openCmd(int32_t argc, int8_t *argv[]);
int32_t readCmd(int32_t argc, int8_t *argv[]);
int32_t writeCmd(int32_t argc, int8_t *argv[]);
int32_t ioctlCmd(int32_t argc, int8_t *argv[]);
int32_t closeCmd(int32_t argc, int8_t *argv[]);
#endif /* USE_CMDLINE */
#endif /* DEVIO_H_ */
